package estore.network;

import estore.model.Product;
import estore.model.User;
import estore.service.ProductService;
import estore.service.UserService;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 商城服务器端程序 - 完善版
 */
public class EStoreServer {
    private final ProductService productService;
    private final UserService userService;
    private final int port;

    // 存储用户购物车和订单数据
    private final Map<String, Map<String, Integer>> userCarts = new HashMap<>();
    private final Map<String, List<Map<String, Object>>> userOrders = new HashMap<>();

    public EStoreServer(int port) {
        this.port = port;
        this.productService = new ProductService();
        this.userService = new UserService();
        System.out.println("商城服务器初始化完成");
    }

    public void start() {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("商城服务器启动成功，监听端口: " + port);
            System.out.println("等待客户端连接...");

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("客户端连接成功: " + clientSocket.getInetAddress().getHostAddress());
                new Thread(() -> handleClient(clientSocket)).start();
            }
        } catch (IOException e) {
            System.err.println("服务器启动失败: " + e.getMessage());
        }
    }

    private void handleClient(Socket clientSocket) {
        try (ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
             ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream())) {

            // 读取请求类型
            String request = (String) ois.readObject();
            System.out.println("收到客户端请求: " + request);

            Object response;
            // 根据请求类型决定是否需要读取额外数据
            if (requiresAdditionalData(request)) {
                Object data = ois.readObject();
                response = processRequest(request, data);
            } else {
                response = processRequest(request, null);
            }

            oos.writeObject(response);
            oos.flush();
            System.out.println("请求处理完成: " + request);

        } catch (IOException | ClassNotFoundException e) {
            System.err.println("处理客户端请求时发生错误: " + e.getMessage());
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                System.err.println("关闭客户端连接时发生错误: " + e.getMessage());
            }
        }
    }

    private boolean requiresAdditionalData(String request) {
        return request.equals("USER_LOGIN") || request.equals("USER_REGISTER") ||
                request.equals("ADD_PRODUCT") || request.equals("UPDATE_PRODUCT") ||
                request.equals("DELETE_PRODUCT") || request.equals("CHECKOUT") ||
                request.equals("CHANGE_PASSWORD") || request.equals("GET_PRODUCT");
    }

    @SuppressWarnings("unchecked")
    private Object processRequest(String request, Object data) {
        try {
            // 提取会话信息
            User currentUser = extractUserFromRequest(data);

            switch (request.toUpperCase()) {
                case "GET_ALL_PRODUCTS":
                    List<Product> products = productService.getAllProducts();
                    System.out.println("返回所有商品数据，数量: " + products.size());
                    return products;

                case "GET_ALL_USERS":
                    if (!hasAdminPermission(currentUser)) {
                        return "ERROR: 无权限访问用户数据";
                    }
                    List<User> users = userService.getAllUsers();
                    return users;

                case "GET_SALES_STATS":
                    if (!hasAdminPermission(currentUser)) {
                        return "ERROR: 无权限访问销售统计";
                    }
                    return getSalesStatistics();

                case "BACKUP_DATA":
                    if (!hasAdminPermission(currentUser)) {
                        return "ERROR: 无权限进行数据备份";
                    }
                    boolean backupResult = productService.backupData();
                    userService.backupData();
                    return backupResult ? "SUCCESS: 数据备份成功" : "ERROR: 数据备份失败";

                case "SAVE_DATA":
                    productService.saveData();
                    userService.saveData();
                    return "SUCCESS: 数据保存成功";

                case "EXIT":
                    System.out.println("客户端请求退出");
                    return "SUCCESS: 服务器连接关闭";

                case "USER_LOGIN":
                    return processUserLogin(data);

                case "USER_REGISTER":
                    return processUserRegistration(data);

                case "ADD_PRODUCT":
                    if (!hasAdminPermission(currentUser)) {
                        return "ERROR: 无权限添加商品";
                    }
                    return productService.addProduct((Product) data);

                case "UPDATE_PRODUCT":
                    if (!hasAdminPermission(currentUser)) {
                        return "ERROR: 无权限修改商品";
                    }
                    return productService.updateProduct((Product) data);

                case "DELETE_PRODUCT":
                    if (!hasAdminPermission(currentUser)) {
                        return "ERROR: 无权限删除商品";
                    }
                    return productService.deleteProduct((String) data);

                case "GET_PRODUCT":
                    return productService.getProductById((String) data);

                case "CHECKOUT":
                    return processCheckout(data);

                case "CHANGE_PASSWORD":
                    return processChangePassword(data);

                default:
                    return "ERROR: 未知的请求命令";
            }
        } catch (Exception e) {
            System.err.println("处理请求时发生异常: " + e.getMessage());
            return "ERROR: 处理请求时发生异常 - " + e.getMessage();
        }
    }

    @SuppressWarnings("unchecked")
    private Object processUserLogin(Object data) {
        Map<String, String> credentials = (Map<String, String>) data;
        String username = credentials.get("username");
        String password = credentials.get("password");

        User user = userService.authenticateUser(username, password);
        if (user != null) {
            // 初始化用户购物车
            userCarts.putIfAbsent(username, new HashMap<>());
            System.out.println("用户登录成功: " + username);
            return user;
        } else {
            return "ERROR: 用户名或密码错误";
        }
    }

    private Object processUserRegistration(Object data) {
        User newUser = (User) data;
        if (userService.getUserByUsername(newUser.getUsername()) != null) {
            return "ERROR: 用户名已存在";
        }

        boolean success = userService.addUser(newUser);
        return success ? "SUCCESS" : "ERROR: 用户注册失败";
    }

    @SuppressWarnings("unchecked")
    private Object processCheckout(Object data) {
        Map<String, Object> checkoutData = (Map<String, Object>) data;
        String username = (String) checkoutData.get("userId");
        Map<String, Integer> cart = (Map<String, Integer>) checkoutData.get("cart");

        // 验证库存
        for (Map.Entry<String, Integer> entry : cart.entrySet()) {
            Product product = productService.getProductById(entry.getKey());
            if (product == null) {
                return "ERROR: 商品不存在: " + entry.getKey();
            }
            if (product.getStock() < entry.getValue()) {
                return "ERROR: 商品库存不足: " + product.getName();
            }
        }

        // 更新库存并创建订单
        double totalAmount = 0.0;
        for (Map.Entry<String, Integer> entry : cart.entrySet()) {
            Product product = productService.getProductById(entry.getKey());
            product.setStock(product.getStock() - entry.getValue());
            productService.updateProduct(product);
            totalAmount += product.getPrice() * entry.getValue();
        }

        // 记录订单
        Map<String, Object> order = new HashMap<>();
        order.put("items", new HashMap<>(cart));
        order.put("totalAmount", totalAmount);
        order.put("timestamp", System.currentTimeMillis());

        userOrders.putIfAbsent(username, new java.util.ArrayList<>());
        userOrders.get(username).add(order);

        // 清空购物车
        userCarts.remove(username);

        System.out.println("用户 " + username + " 结算成功，金额: " + totalAmount);
        return "SUCCESS";
    }

    @SuppressWarnings("unchecked")
    private Object processChangePassword(Object data) {
        Map<String, String> passwordData = (Map<String, String>) data;
        String username = passwordData.get("username");
        String newPassword = passwordData.get("newPassword");

        User user = userService.getUserByUsername(username);
        if (user != null) {
            user.setPassword(newPassword);
            userService.updateUser(user);
            return "SUCCESS: 密码修改成功";
        }
        return "ERROR: 用户不存在";
    }

    private Map<String, Object> getSalesStatistics() {
        Map<String, Object> stats = new HashMap<>();
        // 这里实现销售统计逻辑
        stats.put("totalSales", calculateTotalSales());
        stats.put("totalOrders", calculateTotalOrders());
        stats.put("bestSellingProduct", getBestSellingProduct());
        return stats;
    }

    private double calculateTotalSales() {
        return userOrders.values().stream()
                .flatMap(List::stream)
                .mapToDouble(order -> (Double) order.get("totalAmount"))
                .sum();
    }

    private long calculateTotalOrders() {
        return userOrders.values().stream()
                .mapToLong(List::size)
                .sum();
    }

    private String getBestSellingProduct() {
        // 简化实现，实际应该统计所有订单中的商品销量
        Map<String, Integer> productSales = new HashMap<>();

        userOrders.values().stream()
                .flatMap(List::stream)
                .forEach(order -> {
                    Map<String, Integer> items = (Map<String, Integer>) order.get("items");
                    items.forEach((productId, quantity) -> {
                        productSales.merge(productId, quantity, Integer::sum);
                    });
                });

        return productSales.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(entry -> {
                    Product product = productService.getProductById(entry.getKey());
                    return product != null ?
                            product.getName() + " (销量: " + entry.getValue() + ")" : "无销售数据";
                })
                .orElse("无销售数据");
    }

    private User extractUserFromRequest(Object data) {
        if (data instanceof Map) {
            Map<?, ?> requestData = (Map<?, ?>) data;
            // 从请求数据中提取用户信息
            if (requestData.containsKey("username")) {
                String username = (String) requestData.get("username");
                return userService.getUserByUsername(username);
            }
        }
        return null;
    }

    private boolean hasAdminPermission(User user) {
        return user != null && "admin".equals(user.getRole());
    }

    /**
     * 验证用户权限
     */
    private boolean hasPermission(User user, String requiredRole) {
        if (user == null) return false;
        return requiredRole.equals(user.getRole());
    }

    public static void main(String[] args) {
        int port = 8888;
        if (args.length > 0) {
            try {
                port = Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                System.err.println("端口参数无效，使用默认端口8888");
            }
        }

        EStoreServer server = new EStoreServer(port);
        server.start();
    }
}

/**
 * 会话管理器（新增类）
 */
class SessionManager {
    private static final Map<String, User> activeSessions = new HashMap<>();

    public static String createSession(User user) {
        String sessionId = generateSessionId();
        activeSessions.put(sessionId, user);
        return sessionId;
    }

    public static User validateSession(String sessionId) {
        return activeSessions.get(sessionId);
    }

    public static void invalidateSession(String sessionId) {
        activeSessions.remove(sessionId);
    }

    private static String generateSessionId() {
        return java.util.UUID.randomUUID().toString();
    }
}